package eu.gegenleitner.esspacc.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.security.SecureRandom;
import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.sun.mail.smtp.SMTPTransport;

import eu.gegenleitner.esspacc.ca.CSRChecker;
import eu.gegenleitner.esspacc.ca.Certifier;
import eu.gegenleitner.esspacc.xmlSignature.XMLSignatureVerifier;

/**
 * Servlet implementation class Service
 */
@WebServlet(description = "CA-Service that provides Certificates for given CSRs", urlPatterns = { "/Service" })
public class Service extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final String SMTP_HOST_URL = "YOUR_SMTP_HOST";
	private static final String SENDER_EMAIL_ADDRESS = "YOUR_EMAIL_ADDRESS";
	private static final String SMTP_USER = "<YOUR_PASSWORD";
	private static final String SMTP_PASSWORD = "<YOUR_PASSWORD>";
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Service() {
        super();
    }


	@Override
	public void init() throws ServletException {
		org.apache.xml.security.Init.init();
		super.init();
	}
	
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.sendRedirect(request.getContextPath() + "/index.html");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		session.setMaxInactiveInterval(300);
		PrintWriter pr = response.getWriter();
		if( request.getParameter("zea") != null && !request.getParameter("zea").isEmpty() ) {
			try {
				String xmlSignature = request.getParameter("zea");
				XMLSignatureVerifier veri = new XMLSignatureVerifier();
				if( !veri.isXMLSignatureValid(xmlSignature) )
					throw new Exception(Messages.xmlSignatureInvalid);
				
				String csr = veri.getSignedObjectFromXMlSignature(xmlSignature);
				CSRChecker csrC = new CSRChecker(csr);
				if( !csrC.isValidCSR() )
					throw new Exception(Messages.csrInvalid);
				
				session.setAttribute("zea", csrC);
				String token = generateToken();
				session.setAttribute("token", token);
				sendTokenViaMail(token, csrC.getMailAddress());
				pr.write(Messages.mailSent);
			} catch(Exception e) {
				pr.write(e.getMessage());
				e.printStackTrace();
			}
		} else if( !request.getParameter("token").isEmpty() && session.getAttribute("token") != null ) {
			try {
				if( !request.getParameter("token").equals((String)session.getAttribute("token")) )
					throw new Exception(Messages.tokenInvalid);
				Certifier certy = new Certifier();
				String chain = certy.generateCertFromCSR((CSRChecker)session.getAttribute("zea"), getServletContext().getRealPath("/WEB-INF/keystore.jks") );
				pr.write(chain);
			} catch(Exception e) {
				pr.write(e.getMessage());
				e.printStackTrace();
			}
		} else {
			pr.write(Messages.noAction);
		}
		pr.close();
	}
	
	private String generateToken() {
		String charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		SecureRandom sr = new SecureRandom();
		String token = "";
		for(int i = 1; i <= 16; i++) {
			int randomPositionInCharset = sr.nextInt(charset.length());
			if( i % 4 == 0 && i < 16) {
				token  += charset.charAt(randomPositionInCharset) + "-";
			} else {
				token  += charset.charAt(randomPositionInCharset);
			}
		}
		return token;
	}
	
	private void sendTokenViaMail(String token, String mailAddress) throws AddressException, MessagingException {
		System.out.println(token + "@" + mailAddress);
		Properties props = System.getProperties();
		props.put("mail.smtps.host",SMTP_HOST_URL);
		props.put("mail.smtps.auth","true");
		Session session = Session.getInstance(props, null);
		Message msg = new MimeMessage(session);
		msg.setFrom(new InternetAddress(SENDER_EMAIL_ADDRESS));;
		msg.setRecipients(Message.RecipientType.TO,
		InternetAddress.parse(mailAddress, false));
		msg.setSubject("Your e-mail verification token");
		msg.setText("Your Token is\n\n" + token + "\n\nUse it to validate your E-Mail-Address!");
		msg.setHeader("X-Mailer", "ESSPACC-CA-MailerDeamon");
		msg.setSentDate(new Date());
		SMTPTransport t =
		    (SMTPTransport)session.getTransport("smtps");
		t.connect(SMTP_HOST_URL, SMTP_USER, SMTP_PASSWORD);
		t.sendMessage(msg, msg.getAllRecipients());
		System.out.println("Response: " + t.getLastServerResponse());
		t.close();
	}

}
